/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.plechinger.mcremote.server.craft;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.logging.Logger;

/**
 *
 * @author Lukas
 */
class CraftController implements Observer {

    private static final Logger LOG = Logger.getLogger(CraftController.class.getName());
    private Properties properties;
    private boolean started = false;
    private boolean run = false;
    private String waitfor;
    private final long TIMEOUT;
    /**
     * Collects entire CraftController Log
     */
    private List<CraftLogElement> log = Collections.synchronizedList(new ArrayList<CraftLogElement>());
    private List<CraftLogElement> commandLog = Collections.synchronizedList(new ArrayList<CraftLogElement>());
    CraftCommander commander;

    public CraftController(Properties properties) throws FileNotFoundException {
        this.properties = properties;
        commander = CraftCommander.build(new File(properties.getProperty("craft.folder", "")), properties.getProperty("craft.command", "java -Xmx1024M -Xms1024M -jar minecraft_server.jar nogui"));
        commander.addObserver(this);
        TIMEOUT = Long.parseLong(properties.getProperty("craft.commandTimeout", "5000"));
    }

    public void start() throws CraftServerStatusException {
        commandLog = Collections.synchronizedList(new ArrayList<CraftLogElement>());
        log = Collections.synchronizedList(new ArrayList<CraftLogElement>());
        commander.startServer();
        while (!started) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
        }
        LOG.info("Server started");
    }

    public void stop() throws CraftServerStatusException {
        commander.stopServer();
        while (started) {
            try {
                Thread.sleep(100);
            } catch (Exception e) {
            }
        }
        LOG.info("Server stopped");
    }

    public synchronized List<CraftLogElement> command(CraftCommand comm, String... param) throws CraftServerStatusException, CraftServerTimeoutException {
        run = true;
        commandLog.clear();
        waitfor = "Unknown console command.";

        commander.command(comm, param);
        commander.command(CraftCommand.NULL);

        try {
            Thread.sleep(TIMEOUT);
        } catch (Exception e) {
        }
        if (run) {
            throw new CraftServerTimeoutException("Server request timed out!");
        }

        return commandLog;
    }

    public List<CraftLogElement> getLog() {
        return log;
    }

    public void update(Observable o, Object arg) {
        if (arg instanceof CraftLogElement) {
            CraftLogElement element = (CraftLogElement) arg;
            log.add(element);
            if (run) {

                if (element.getMessage().contains(waitfor)) {
                    run = false;
                } else {
                    commandLog.add(element);
                }
            }

            if (!started) {
                if (element.getMessage().contains("Done (")) {
                    started = true;
                    onStarted();
                }
            } else {
                if (element.getMessage().contains("Saving chunks")) {
                    started = false;
                    onStopped();
                }
            }
        }
    }

    public boolean isStarted() {
        return started;
    }

    private void onStarted() {
        //LOG.info("Call onstarted callback");
    }

    private void onStopped() {
        //LOG.info("Call onstopped callback");
    }
}
